package com.left.tcc.score.service;

import com.left.tcc.commons.enums.TccEnum;
import com.left.tcc.score.dto.ScoreAccountDTO;
import com.left.tcc.score.entity.ScoreAccount;
import com.left.tcc.score.entity.ScoreDetail;
import com.left.tcc.score.mapper.ScoreAccountMapper;
import com.left.tcc.score.mapper.ScoreDetailMapper;
import lombok.extern.slf4j.Slf4j;
import org.dromara.hmily.annotation.Hmily;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@Slf4j
public class ScoreAccountService {
    @Autowired
    private ScoreAccountMapper scoreAccountMapper;
    @Autowired
    private ScoreDetailMapper scoreDetailMapper;

    @Hmily(confirmMethod = "confirmMethod",cancelMethod = "cancelMethod")
    @Transactional
    public  void decrease(ScoreAccountDTO obj){
        log.info("-------进入积分的try-------");
        //第一步:检验积分
        ScoreAccount  scoreAccount = new ScoreAccount();
        scoreAccount.setUserId(obj.getUserId());
        scoreAccount = this.scoreAccountMapper.selectOne(scoreAccount);
        if(scoreAccount.getTotalScore()<=0||scoreAccount.getTotalScore()<obj.getScore()){
            throw new RuntimeException("积分不足");
        }
        //第二步：幂等性校验
        ScoreDetail scoreDetail = new ScoreDetail();
        scoreDetail.setOrderNo(obj.getOrderNo());
        if(this.scoreDetailMapper.selectOne(scoreDetail)!=null){
            throw new RuntimeException("存在订单号！");
        }
        //第三步：插入积分明细
        BeanUtils.copyProperties(obj,scoreDetail);
        scoreDetail.setTxStatus(TccEnum.TRY.getCode());
        this.scoreDetailMapper.insertSelective(scoreDetail);

        //第四步：减库存
        ScoreAccount updateInventory=new ScoreAccount();
        updateInventory.setUserId(obj.getUserId());
        //库存处理
        updateInventory.setTotalScore(-obj.getScore());
        //冻结处理
        updateInventory.setLockScore(+obj.getScore());
        this.scoreAccountMapper.decrease(updateInventory);

    }

    @Transactional
    public void confirmMethod(ScoreAccountDTO obj){

        log.info("-------进入积分的confirm-------");
        //第一步：幂等性校验
        ScoreDetail scoreDetail=new ScoreDetail();
        scoreDetail.setOrderNo(obj.getOrderNo());
        scoreDetail=this.scoreDetailMapper.selectOne(scoreDetail);
        if(scoreDetail.getTxStatus()==TccEnum.CONFIRM.getCode()){
            throw new RuntimeException("该订单号，已经confirm!");
        }

        //第二步：修改订单明细状态，作用：幂等性校验
        ScoreDetail updateScoreDetail =new ScoreDetail();
        updateScoreDetail.setId(updateScoreDetail.getId());
        updateScoreDetail.setTxStatus(TccEnum.CONFIRM.getCode());
        this.scoreDetailMapper.updateByPrimaryKeySelective(updateScoreDetail);

        //第三步：积分处理
        ScoreAccount scoreAccount=new ScoreAccount();
        scoreAccount.setUserId(obj.getUserId());
        //积分处理
        scoreAccount.setTotalScore(0);
        //冻结处理
        scoreAccount.setLockScore(-obj.getScore());
        this.scoreAccountMapper.decrease(scoreAccount);
        //int i=9/0;
    }
    @Transactional
    public  void cancelMethod(ScoreAccountDTO obj){
        log.info("-------进入积分的cancel-------");
        //第一步：幂等性校验
        ScoreDetail scoreDetail=new ScoreDetail();
        scoreDetail.setOrderNo(obj.getOrderNo());
        scoreDetail=this.scoreDetailMapper.selectOne(scoreDetail);
        if(scoreDetail.getTxStatus()==TccEnum.CANCEL.getCode()){
            throw new RuntimeException("该订单号，已经cancel!");
        }

        //第二步：修改订单明细状态，作用：幂等性校验
        ScoreDetail updateScoreDetail =new ScoreDetail();
        updateScoreDetail.setId(scoreDetail.getId());
        updateScoreDetail.setTxStatus(TccEnum.CANCEL.getCode());
        this.scoreDetailMapper.updateByPrimaryKeySelective(updateScoreDetail);

        //第三步：库存处理
        ScoreAccount scoreAccount=new ScoreAccount();
        scoreAccount.setUserId(obj.getUserId());
        //库存处理
        scoreAccount.setTotalScore(obj.getScore());
        //冻结处理
        scoreAccount.setLockScore(-obj.getScore());
        this.scoreAccountMapper.decrease(scoreAccount);
    }


}
